﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using POC.Configuration;
using Microsoft.WindowsAzure.Storage.Table.DataServices;
using System.Net;
using System.Net.Http;

namespace Blogger.UI.Models
{
    public enum PostStatus
    {
        New=0,
        Draft=1,
        Saved=2,
        Updated=3,
        Published =10
    }
    public class Blog : TableServiceEntity
    {
        public Blog(): this("BLOGS",Guid.NewGuid().ToString())
        {
        }
        public Blog(string partition, string rowId)
            : base(partition, rowId)
        {
            IP = WebUtil.GetClientIpAddress();
        }
        public string ID { get; set; }
        public string Name { get; set; }
        public string Title { get; set; }
        public string Category { get; set; }
        public string Body { get; set; }
        public string User { get; set; }
        public string IP { get; set; }
    }
    public class Posting: TableServiceEntity
    {
        public Posting()
            : this("POSTS", Guid.NewGuid().ToString())
        {
        }
        public Posting(string partition, string rowId)
             : base(partition, rowId)
        {
            IP = WebUtil.GetClientIpAddress();
        }
        public string ID { get; set; }
        public string BlogID { get; set; }
        public string Name { get; set; }
        public string Title { get; set; }
        public string Category { get; set; }
        public string Body { get; set; }
        public string User { get; set; }
        public string IP { get; set; }
        public int Status{ get; set; }

        public List<Comment> Comments { get; set; }
        public List<Rating> Ratings { get; set; }
    }
    public class Comment: TableServiceEntity
    {
        public Comment()
            : this("COMMENTS", Guid.NewGuid().ToString())
        {
        }
        public Comment(string partition, string rowId)
             : base(partition, rowId)
        {
            
        }
        public string ID { get; set; }
        public string PostID { get; set; }
        public string Body { get; set; }
    }
    public class Rating: TableServiceEntity
    {
        public Rating()
            : this("RATINGS", Guid.NewGuid().ToString())
        {
        }
        public Rating(string partition, string rowId)
             : base(partition, rowId)
        {
            
        }
        public string ID { get; set; }
        public string PostID { get; set; }
        public int Rate { get; set; }
    }

    public static class DataTypeExtn
    {
        public static int? ToID(this Blog blog)
        {
            int? coolId = blog.ID.ToNullableInt();
            return coolId;
        }
        public static long? ToBlogID(this Posting post)
        {
            long? coolId = post.BlogID.ToNullableLong();
            return coolId;
        }
        public static long? ToID(this Posting post)
        {
            long? coolId = post.ID.ToNullableLong();
            return coolId;
        }
    }
    public static class WebUtil
    {
        public static string GetClientIpAddress()
        {
            string ip = HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"];
            if (string.IsNullOrEmpty(ip))
            {

            }
            return ip;
        }
        public static string GetClientIpAddress(HttpRequestBase request)
        {
            try
            {
                var userHostAddress = request.UserHostAddress;

                // Attempt to parse.  If it fails, we catch below and return "0.0.0.0"
                // Could use TryParse instead, but I wanted to catch all exceptions
                IPAddress.Parse(userHostAddress);

                var xForwardedFor = request.ServerVariables["X_FORWARDED_FOR"];

                if (string.IsNullOrEmpty(xForwardedFor))
                    return userHostAddress;

                // Get a list of public ip addresses in the X_FORWARDED_FOR variable
                var publicForwardingIps = xForwardedFor.Split(',').Where(ip => !IsPrivateIpAddress(ip)).ToList();

                // If we found any, return the last one, otherwise return the user host address
                return publicForwardingIps.Any() ? publicForwardingIps.Last() : userHostAddress;
            }
            catch (Exception)
            {
                // Always return all zeroes for any failure (my calling code expects it)
                return "0.0.0.0";
            }
        }

        private static bool IsPrivateIpAddress(string ipAddress)
        {
            // http://en.wikipedia.org/wiki/Private_network
            // Private IP Addresses are: 
            //  24-bit block: 10.0.0.0 through 10.255.255.255
            //  20-bit block: 172.16.0.0 through 172.31.255.255
            //  16-bit block: 192.168.0.0 through 192.168.255.255
            //  Link-local addresses: 169.254.0.0 through 169.254.255.255 (http://en.wikipedia.org/wiki/Link-local_address)

            var ip = IPAddress.Parse(ipAddress);
            var octets = ip.GetAddressBytes();

            var is24BitBlock = octets[0] == 10;
            if (is24BitBlock) return true; // Return to prevent further processing

            var is20BitBlock = octets[0] == 172 && octets[1] >= 16 && octets[1] <= 31;
            if (is20BitBlock) return true; // Return to prevent further processing

            var is16BitBlock = octets[0] == 192 && octets[1] == 168;
            if (is16BitBlock) return true; // Return to prevent further processing

            var isLinkLocalAddress = octets[0] == 169 && octets[1] == 254;
            return isLinkLocalAddress;
        }
        private static string GetClientIp(HttpRequestMessage request)
        {
            if (request.Properties.ContainsKey("MS_HttpContext"))
            {
                return ((HttpContextWrapper)request.Properties["MS_HttpContext"]).Request.UserHostAddress;
            }
            //else if (request.Properties.ContainsKey(RemoteEndpointMessageProperty.Name))
            //{
            //    RemoteEndpointMessageProperty prop;
            //    prop = (RemoteEndpointMessageProperty)this.Request.Properties[RemoteEndpointMessageProperty.Name];
            //    return prop.Address;
            //}
            else
            {
                return null;
            }
        }
    }
}